""" 此文件包括窗口：归档,查阅全部已归档病案、修改已归档信息、查阅病案复印历史信息及修改、help等 """

import PySimpleGUI as sg 
from datetime import datetime,timedelta
from itertools import chain
from objects import MR
from sqlhlper import SQLHLPER


# calendarbutton图标的BASE64字符串
img_data_calendar='iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAiElEQVQ4jbWR0QmAMBBD3wgdwRG6gY7iJnYzb4O6gY7ih1c8tSitGgg0vRACgY8RgO7m3qnnAgFGYAaivnOM6kn6EFDaQOwhiQZwNwFOPZeARZNLuOQalEByQpQ94I32+icn7z8NRtMgzZUa2Pn+aRCAgW3vRt8D+3SPAdUNJqAtZLQBoZLvsQItcDy/JhvEGAAAAABJRU5ErkJggg=='
# 主窗口搜索图标
img_data_search='iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAB9ElEQVRYhe2WIUzDUBCGP7EEBAKxBDMxMTExOTGBQCAImUBMIBAViIkJSBBIEgQCiUCgAIGYRJCAQEAyQQICMbGECUhIQCAmJhBD3L28x9KNvbZUEC6p2K3/3feuvbvCv01uJaAGBHotAjNpJK4DHWAQcvWBJpD/jcR54NpJ1gZOgQ1gH7gCevpfD6lKYlZzgl8z/oQN595zIBM3eQ740KANx1/Gnjw3pCkAdwqxEyf5FHCsgTbVlwF2gU/s48iHaEvALfACLEcFCLBlN3agvmdgFciO0Vf13gciPooHvp9wQX93gdkJY5ypZtE3eUGFHcfXVN+SR5w11Rz6AtRUeOL47oEn/AZOReNc+gIEKtwa8lV9AyEd1PYVrZNAGwFzwBtw4ytcwg6TOFbWOE1fYRbp9feYAA0F2I0ivlLxQgyAG41RiCKuIFXoANMR9Ob0d1GSG9vXIHueujx2KQ2QrRnJppEWGiBjeJIZUEVGtQF/jQtRwo7lriYIAylgd4XbQcUkIDLITHC34CPyUXKBrGzjf0XK/4lM1MQgQKpxhLSn+znWA1rI7M8A8yMgzHsRC8JYFnnZRq3kMAjjSwziJ/sJojFCl6itKEAYRJ+UPudrIRB1pApBGgDDENvYUV9OC8BA9LHd00ozubEi0gEB0XbMH7Yv1filjU9VD18AAAAASUVORK5CYII='

# 设置calendar控件的月和周
month_names_list=[str(m)+'月' for m in range(1,13)]   #calendar 的自定义月份列表
day_abbreviations_list=['周日','周一','周二','周三','周四','周五','周六']    #calendar 的自定义星期列表




# -------------Calendar函数---------------------

def PopupCalendar(start_year=None,start_month=None,start_day=None,format='%Y-%m-%d %H:%M:%S',begin_at_sunday_plus=1,month_names=month_names_list,day_abbreviations=day_abbreviations_list,no_titlbar=False,title='选择日期',keep_on_top=True,close_when_chosen=True):
    datetime_tuple=sg.popup_get_date(start_mon=start_month,start_day=start_day,start_year=start_year,begin_at_sunday_plus=begin_at_sunday_plus,no_titlebar=no_titlbar,title=title,keep_on_top=keep_on_top,close_when_chosen=close_when_chosen,month_names=month_names,day_abbreviations=day_abbreviations)
    if not datetime_tuple is None:
        datetime_tmp=datetime(datetime_tuple[2],datetime_tuple[0],datetime_tuple[1],datetime.now().time().hour,datetime.now().time().minute,datetime.now().time().second).strftime(format)
        return datetime_tmp


# -------------从数据库获取科室名称---------------

def GetGroupNames():
    
    sqlstr="select group_name from groupname"
    rs=SQLHLPER.selectall(sqlstr)
    group_name_list=list(chain.from_iterable(rs))    # 二维列表转换为一维列表
    
    return group_name_list



# ------------从数据库获取非工作日列表-------------

def GetDayOff():

    sqlstr="select offday from dayoff order by id desc"
    rs=SQLHLPER.selectall(sqlstr)
    dayoff_list=list(chain.from_iterable(rs))

    return dayoff_list




# -------------病案归档窗口--------------

def MRFilingWindow(mr=MR()):
    layout=[
    [sg.Text('病案号：',size=(15,1)),sg.Input(mr.mr_num,size=(20,1),key='-mr_num-')],
    [sg.Text('住院号：',size=(15,1)),sg.Input(mr.hospital_num,size=(20,1),key='-hospital_num-')],
    [sg.Text('患者姓名：',size=(15,1)),sg.Input(mr.pat_name,size=(20,1),key='-pat_name-')],
    [sg.Text('患者身份证号：',size=(15,1)),sg.Input(mr.id_num,size=(20,1),key='-pat_id_num-')],
    [sg.Text('患者住址：',size=(15,1)),sg.Input(mr.addr,size=(40,1),key='-addr-')],
    [sg.Text('入院日期：',size=(15,1)),sg.Input(mr.in_date,size=(20,1),key='-in_date-'),sg.Button('',image_data=img_data_calendar,key='-in_date_calendar-')],
    [sg.Text('出院日期：',size=(15,1)),sg.Input(mr.dis_date,size=(20,1),key='-dis_date-'),sg.Button('',image_data=img_data_calendar,key='-dis_date_calendar-')],
    [sg.Text('出院科室：',size=(15,1)),sg.Combo(mr.dis_group,size=(20,1),key='-dis_group-')],
    [sg.Text('离院方式：',size=(15,1)),sg.Input(mr.dis_way,size=(20,1),key='-dis_way-')],
    [sg.Text('主要诊断：',size=(15,1)),sg.Input(mr.pd,size=(20,1),key='-pd-')],
    [sg.Text('住院医生：',size=(15,1)),sg.Input(mr.doctor,size=(20,1),key='-doctor-')],
    [sg.Text('归档时间：',size=(15,1)),sg.Input(mr.filing_time,size=(20,1),key='-filing_time-'),sg.Button('',image_data=img_data_calendar,key='-filing_time_calendar-')],
    [sg.Text('')],
    [sg.Button('保存并继续',key='-savenew-',bind_return_key=True),sg.Button('保存',key='-save-'),sg.Text('     '),sg.Button('取消',key='-cancel-')]
    ]

    window=sg.Window('病案归档',layout,font=('Microsoft YaHei',12))
    return window



# ----------病案借阅历史记录查阅窗口---------

def MRBorrowLogWindow():

    t_heading=['病案号','住院号','患者姓名','借阅人姓名','出院时间','借阅时间','归还时间']
    t_data=[[' '*7,' '*8,' '*8,' '*8,' '*20,' '*20,' '*20]]      #默认数据全部为空
    t_visible_col_map=[True,True,True,True,True,True,True]       #隐藏最后一列

    col_layout=[        
        [sg.Table(t_data,headings=t_heading,key='-table-',visible_column_map=t_visible_col_map,display_row_numbers=True,row_height=23,vertical_scroll_only=False)],
        [sg.Text('',size=(40,1),key='-display_table_info-')]
    ]

    layout=[[sg.Column([[sg.Text('',size=(1,9),key='-emp-')],[sg.Input('',size=(40,1),key='-in-',font=('Microsoft YaHei',16)),sg.Button('',image_data=img_data_search,key='-search-',bind_return_key=True)]],justification='center',element_justification='center')],
        [sg.Column(col_layout,justification='center',element_justification='center',visible=False,key='-table_col-')]
        ]

    window=sg.Window('病案借阅历史记录',layout,size=(1000,650),resizable=True,font=('Microsoft YaHei',10))

    return window



# -----------查阅病案复印历史记录窗口---------

def MRCopyedLogWindow():

    t_heading=['病案号','住院号','患者姓名','复印人姓名','复印人身份证号','与患者关系','复印件用途','复印时间','ID']
    t_data=[[' '*7,' '*8,' '*8,' '*8,' '*18,' '*15,' '*30,' '*20,' '*6]]      #默认数据全部为空
    t_visible_col_map=[True,True,True,True,True,True,True,True,False]       #隐藏最后一列

    col_layout=[
        [sg.Input('',size=(40,1),key='-in-',font=('Microsoft YaHei',14)),sg.Button('',image_data=img_data_search,key='-search-',button_color=(None,'white'),bind_return_key=True)],
        [sg.Table(t_data,headings=t_heading,key='-table-',visible_column_map=t_visible_col_map,vertical_scroll_only=False,display_row_numbers=True,right_click_menu=['menu',['删除::-del-']])],
        [sg.Text('数据共？行',size=(40,1),key='-disp_table_info-')]
    ]

    layout=[[sg.Column(col_layout,justification='center',element_justification='center')]]

    window=sg.Window('病案复印历史记录',layout,resizable=True,size=(1000,650))

    return window




# ----------其它档案借阅登记窗口------------

def ArcBorrowReginWindow():

    layout=[
        [sg.Text('档案号',size=(8,1)),sg.Input('',size=(30,1),key='-archives_num-')],
        [sg.Text('档案描述',size=(8,1)),sg.Input('',size=(30,1),key='-archives_contents-')],
        [sg.Text('借阅人',size=(8,1)),sg.Input('',size=(30,1),key='-borrower-')],
        [sg.Text('借阅时间',size=(8,1)),sg.Input(datetime.now().strftime('%Y-%m-%d %H:%M:%S'),size=(30,1),key='-borrow_time-'),sg.Button('',target='-borrow_time-',image_data=img_data_calendar,key='-borrow_time_calendar-')],
        [sg.Text('',size=(1,5))],
        [sg.Button(' 保存 ',key='-save-',bind_return_key=True),sg.Button('保存并继续',key='-savenew-'),sg.Text('   '),sg.Button('取消',key='-cancel-')]        
    ]

    window=sg.Window('其它档案归档登记',layout,size=(460,300),font=('Microsoft YaHei',11))

    return window




# ----------其它档案借阅历史记录查阅窗口--------------

def ArcBorrowLogWinow():

    # 获取数据库历史借阅记录
    sqlstr="select  arc_id,arc_content,borrower,borrow_time,ifnull(back_time,''),id from archivesborrow  order by back_time,borrow_time desc limit 20"
    rs=SQLHLPER.selectall(sqlstr)
    if len(rs)>0:
        t_data=[list(item) for item in rs]
    else:
        t_data=[]      

    t_heading=['档案号','档案描述','借阅人','借阅时间','归还时间','ID']
    # t_data=[[' '*30,' '*30,' '*8,' '*20,' '*20,' '*6]]      #默认数据全部为空
    t_visible_col_map=[True,True,True,True,True,False]      #隐藏最后一列

    col_layout=[
        [sg.Input('',size=(40,1),key='-in-',font=('Microsoft YaHei',14)),sg.Button('',image_data=img_data_search,key='-search-',button_color=(None,'white'))],
        [sg.Table(t_data,headings=t_heading,key='-table-',visible_column_map=t_visible_col_map,display_row_numbers=True,col_widths=[20,20,8,20,20,6],auto_size_columns=False,right_click_menu=['menu',['归还::-back-']])],
        [sg.Text('共 {} 条记录'.format(len(rs)),size=(40,1),key='-disp_table_info-')]
    ]

    layout=[
        [sg.Text('')], 
        [sg.Column(col_layout,justification='center',element_justification='center')]               
    ]

    window=sg.Window('其它档案借阅管理',layout,resizable=True,font=('Microsoft YaHei',10))

    return window




# -----------其它档案归还窗口---------------

def ArcBackWindow(id,arc_id,arc_content):

    layout=[
        [sg.Text(id,key='-id-',visible=False)],
        [sg.Text(arc_id)],
        [sg.Text(arc_content)],
        [sg.Text('归还时间:'),sg.Input(datetime.now().strftime('%Y-%m-%d %H:%M:%S'),size=(22,1),key='-back_time-'),sg.CalendarButton('',target='-back_time-',image_data=img_data_calendar,month_names=month_names_list,day_abbreviations=day_abbreviations_list,no_titlebar=False)],
        [sg.Text('')],
        [sg.Button(' 保 存 ',key='-save-'),sg.Button(' 取 消 ',key='-cancel-')]
    ]

    window=sg.Window('归还档案',layout,size=(500,400))
    return window



# ---------修改病案归档信息窗口-------------

def MREditWindow(mr=MR()):    
    
    layout=[
    [sg.Text('病案号：',size=(15,1)),sg.Input(mr.mr_num,size=(20,1),key='-mr_num-')],
    [sg.Text('住院号：',size=(15,1)),sg.Input(mr.hospital_num,size=(20,1),key='-hospital_num-')],
    [sg.Text('患者姓名：',size=(15,1)),sg.Input(mr.pat_name,size=(20,1),key='-pat_name-')],
    [sg.Text('患者身份证号：',size=(15,1)),sg.Input(mr.id_num,size=(20,1),key='-pat_id_num-')],
    [sg.Text('患者住址：',size=(15,1)),sg.Input(mr.addr,size=(40,1),key='-addr-')],
    [sg.Text('入院日期：',size=(15,1)),sg.Input(mr.in_date,size=(20,1),key='-in_date-'),sg.Button('',image_data=img_data_calendar,key='-in_date_calendar-')],
    [sg.Text('出院日期：',size=(15,1)),sg.Input(mr.dis_date,size=(20,1),key='-dis_date-'),sg.Button('',image_data=img_data_calendar,key='-dis_date_calendar-')],
    [sg.Text('出院科室：',size=(15,1)),sg.Combo(GetGroupNames(),default_value=mr.dis_group,size=(20,1),key='-dis_group-')],
    [sg.Text('离院方式：',size=(15,1)),sg.Input(mr.dis_way,size=(20,1),key='-dis_way-')],
    [sg.Text('主要诊断：',size=(15,1)),sg.Input(mr.pd,size=(20,1),key='-pd-')],
    [sg.Text('住院医生：',size=(15,1)),sg.Input(mr.doctor,size=(20,1),key='-doctor-')],
    [sg.Text('归档时间：',size=(15,1)),sg.Input(mr.filing_time,size=(20,1),key='-filing_time-'),sg.Button('',image_data=img_data_calendar,key='-filing_time_calendar-')],
    [sg.Text(mr.id,visible=False,key='-id-')],
    [sg.Button('保存',key='-save-',bind_return_key=True),sg.Text('     '),sg.Button('取消',key='-cancel-')]
    ]

    window=sg.Window('修改病案归档信息',layout,font=('Microsoft YaHei',12))
    return window



# ----------设置窗口optionwindow----------------

def OptionWindow():

    # 设置非工作日tab页
    tab1_layout=[
        [sg.Text('')],
        [sg.Text('添加非工作日：\n在方框内输入日期,以空格分隔，如“20200501 20200502”',font=('Microsoft YaHei',9))],
        [sg.Multiline('',size=(42,3),key='-in_dayoff-',autoscroll=True),sg.Button(' 保 存 ',key='-save_dayoff-'),sg.Text('',size=(5,1))],
        [sg.Listbox(GetDayOff(),select_mode=sg.LISTBOX_SELECT_MODE_EXTENDED,auto_size_text=True,key='-dayoff_listbox-',size=(42,20),right_click_menu=['menu',['删除::-del_dayoff-']])]
    ]
    
    # 设置科室名称tab页
    tab2_layout=[
        [sg.Text('')],
        [sg.Text('添加科室名称：')],
        [sg.Input('',size=(33,1),key='-in_groupname-',font=('Microsoft Yahei',13)),sg.Button(' 添 加 ',key='-save_groupname-',bind_return_key=True)],
        [sg.Listbox(GetGroupNames(),select_mode=sg.LISTBOX_SELECT_MODE_EXTENDED,auto_size_text=True,key='-groupnames_listbox-',size=(40,10),right_click_menu=['menu',['修改::-edit-','删除::-del_groupname-']])]
    ]

    layout=[
        [sg.TabGroup([[sg.Tab('非工作日',tab1_layout),sg.Tab('科室名称',tab2_layout)]])]
    ]

    window=sg.Window('设置',layout,size=(500,600))
    return window




# ----------查阅病案归档率窗口--------------

def FilingRateWindow():

    # 获取上月第一天和最后一天日期
    year=datetime.now().year if datetime.now().month<12 else datetime.now().year-1
    premonth=12 if datetime.now().month==1 else datetime.now().month-1 
    firstdate=datetime(year,premonth,1).date()

    lastdate=datetime(datetime.now().year,datetime.now().month,1).date()-timedelta(1)

    t_headings=['出院科室/医生','归档病案数','2日归档率%','3日归档率%','7日归档率%']
    t_data=[[' ' for i in range(5)]]

    layout=[
        [sg.Text('日   期：'),sg.Input(firstdate,size=(16,1),key='-firstdate-',disabled=True),sg.Button('',image_data=img_data_calendar,key='-firstdate_calendar-'),
        sg.Text('——'),sg.Input(lastdate,size=(16,1),key='-lastdate-',disabled=True),sg.Button('',image_data=img_data_calendar,key='-lastdate_calendar-')],
        [sg.Text('分类计算：'),sg.Radio('出院科室',group_id='-group-',key='-disgroup-',enable_events=True,default=True),sg.Radio('住院医生',group_id='-group-',key='-doctor-',enable_events=True)],
        [sg.Text('')],
        [sg.Button('    查   询    ',key='-search-',bind_return_key=True)],
        [sg.Table(t_data,headings=t_headings,key='-table-',def_col_width=11,auto_size_columns=False,num_rows=15,row_height=25,right_click_menu=['menu',['导出::-report-']])],
        [sg.Text('',size=(20,1),key='-displaynums-')]
    ]

    window=sg.Window('病案归档率',layout)

    return window


# 病案率计算函数
def FilingCalculator(fdate,ldate,groupby_disgroup=True):

    # 查询出指定日期的病案，计算出归档天数（含节假日）
    sqlstr="select id,DIS_GROUP,DOCTOR,date(dis_date),date(filing_time),JULIANDAY(strftime('%Y-%m-%d',filing_time))-JULIANDAY(DATE(DIS_DATE)) from mrinfo where date(filing_time)>=:fdate and date(filing_time)<=:ldate"
    rs_mr=SQLHLPER.selectall(sqlstr,**{'fdate':fdate,'ldate':ldate})

    mr_list=[list(item) for item in rs_mr]     # turple转换成list，方便append非工作日天数

    SQLHLPER.execute("delete from tempfilingday")     # 清空临时表原有记录

    # 计算非工作日天数，逐条从归档天数中扣减，写入到临时表tempfilingday中，以方便最后分类汇总计算归档率

    for item in mr_list:

        # 查询非工作日表，以便扣减非工作日天数
        sqlstr="select count(offday) from dayoff where date(offday)>=? and date(offday)<=? "
        dayoffs_count=SQLHLPER.selectone(sqlstr,*(item[3],item[4]))

        item.append(dayoffs_count[0])    # append非工作日天数到每条记录

        # 扣减非工作日天数，写入到临时表
        insert_sql="insert into tempfilingday(mrinfo_id,DIS_GROUP,DOCTOR,filing_days) values(?,?,?,?)"
        SQLHLPER.execute(insert_sql,*(item[0],item[1],item[2],item[5]-item[6]))

    # sql语句，利用临时表分类汇总计算病案归档率，分类字段:dis_group

    groupby_disgroup_sql='''
    SELECT tempfilingday.DIS_GROUP,count(tempfilingday.mrinfo_id) as mrcount,
    ROUND(ifnull(workdays2,0)/(count(tempfilingday.mrinfo_id)*1.0)*100,2),
    ROUND(ifnull(workdays3,0)/(count(tempfilingday.mrinfo_id)*1.0)*100,2),
    ROUND(ifnull(workdays7,0)/(count(tempfilingday.mrinfo_id)*1.0)*100,2) 
    from (((tempfilingday LEFT OUTER JOIN (SELECT DIS_GROUP,COUNT(*) as workdays7 from tempfilingday WHERE FILING_DAYS<=7 GROUP BY DIS_GROUP)tmp7d ON tempfilingday.DIS_GROUP=tmp7d.DIS_GROUP)
    LEFT OUTER JOIN (SELECT DIS_GROUP,COUNT(*) as workdays2 from tempfilingday WHERE FILING_DAYS<=2 GROUP BY DIS_GROUP)tmp2d ON tempfilingday.DIS_GROUP=tmp2d.DIS_GROUP)
    LEFT OUTER JOIN (SELECT DIS_GROUP,COUNT(*) as workdays3 from tempfilingday WHERE FILING_DAYS<=3 GROUP BY DIS_GROUP)tmp3d ON tempfilingday.DIS_GROUP=tmp3d.DIS_GROUP)
    GROUP BY tempfilingday.DIS_GROUP ORDER BY tempfilingday.DIS_GROUP
    '''

    # sql语句，利用临时表分类汇总计算病案归档率，分类字段:doctor

    groupby_doctor_sql='''
    SELECT tempfilingday.DOCTOR,count(tempfilingday.mrinfo_id) as mrcount,
    ROUND(ifnull(workdays2,0)/(count(tempfilingday.mrinfo_id)*1.0)*100,2),
    ROUND(ifnull(workdays3,0)/(count(tempfilingday.mrinfo_id)*1.0)*100,2),
    ROUND(ifnull(workdays7,0)/(count(tempfilingday.mrinfo_id)*1.0)*100,2) 
    from (((tempfilingday LEFT OUTER JOIN (SELECT DOCTOR,COUNT(*) as workdays7 from tempfilingday WHERE FILING_DAYS<=7 GROUP BY DOCTOR)tmp7d ON tempfilingday.DOCTOR=tmp7d.DOCTOR)
    LEFT OUTER JOIN (SELECT DOCTOR,COUNT(*) as workdays2 from tempfilingday WHERE FILING_DAYS<=2 GROUP BY DOCTOR)tmp2d ON tempfilingday.DOCTOR=tmp2d.DOCTOR)
    LEFT OUTER JOIN (SELECT DOCTOR,COUNT(*) as workdays3 from tempfilingday WHERE FILING_DAYS<=3 GROUP BY DOCTOR)tmp3d ON tempfilingday.DOCTOR=tmp3d.DOCTOR)
    GROUP BY tempfilingday.DOCTOR ORDER BY tempfilingday.DOCTOR
    '''

    calculator_sql=groupby_disgroup_sql if groupby_disgroup else groupby_doctor_sql

    filingrate=SQLHLPER.selectall(calculator_sql)

    return [list(em) for em in filingrate]     #将tuple转换成list后返回

